package com.ihr360.payroll.service.payroll.impl;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.ihr360.alps.api.ServiceProvider;
import com.ihr360.attendance.AttendancePeriodReport;
import com.ihr360.common.DateRange;
import com.ihr360.commons.exception.Ihr360Exception;
import com.ihr360.commons.lang.CollectionUtils;
import com.ihr360.commons.model.meta.table.DynamicCell;
import com.ihr360.commons.model.type.TaxRole;
import com.ihr360.expr.ExprArray;
import com.ihr360.payroll.calc.StaffSalaryCalcPeriod;
import com.ihr360.payroll.dao.PayrollConfigDemoRepository;
import com.ihr360.payroll.model.dto.salary.demo.PayrollConfigDemo;
import com.ihr360.payroll.model.dto.salary.meta.SalaryField;
import com.ihr360.payroll.service.payroll.PayrollConfigDemoService;
import com.ihr360.payroll.service.payroll.mock.core.MockPersonalSalaryCalcContextHolder;
import com.ihr360.payroll.service.payroll.mock.core.PersonalSalaryCalcContext;
import com.ihr360.payroll.service.payroll.mock.payrollDemo.PayrollConfigDemoSalaryCalcCapable;
import com.ihr360.payroll.service.salarytasklet.step.SalaryCalcContext;
import com.ihr360.payroll.service.salarytasklet.step.calculator.PersonalSalaryCalculator;
import com.ihr360.payroll.service.salarytasklet.step.processor.TaxTableProcessor;
import com.ihr360.rest.reposity.SimpleRestReposity;
import com.ihr360.rest.service.AbstractSimpleRestServiceImpl;
import org.junit.Assert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class PayrollConfigDemoServiceImpl extends AbstractSimpleRestServiceImpl<PayrollConfigDemo, Long> implements PayrollConfigDemoService {


    Logger logger = LoggerFactory.getLogger(PayrollConfigDemoServiceImpl.class);

    @Autowired
    private PayrollConfigDemoRepository payrollConfigRepository;

    @Override
    public SimpleRestReposity<PayrollConfigDemo, Long> getSimpleRestReposity() {
        return payrollConfigRepository;
    }

    @Autowired
    private PayrollConfigDemoSalaryCalcCapable personalSalaryCalcCapable;

    @Override
    public Map<String, DynamicCell> demoSalaryCalc(List<SalaryField> salaryFields) {
        PersonalSalaryCalcContext mockContext = MockPersonalSalaryCalcContextHolder.getDemoPersonalSalaryCalcContext();
        mockContext.setSalaryFields(salaryFields);

        SalaryCalcContext context = null;
        try {
            context = personalSalaryCalcCapable.buildContext();
            context.workingCalendarHolder = personalSalaryCalcCapable.workingCalendarHolderOfMarch();

        } catch (Exception e) {
            logger.error("示例数据计算失败:" + e.getMessage(), e);
            return Maps.newHashMap();
        }

        PersonalSalaryCalculator calculator = MockPersonalSalaryCalcContextHolder.getCurrentCalculator();
        buildCalcRange();

        calculator.initContext(context);
        calculator.setIsSinglePhase(true);
        calculator.setIsSingleTerm(true);

        //收入项目部分
        Map<String, DynamicCell> inputSalary = buildInputSalary();
        //员工的服务引用数据
        Map<String, Map<String, Object>> staffRefServiceData = buildRefServiceData();
        //薪资档案数据
        StaffSalaryCalcPeriod staffPeriodSalary = personalSalaryCalcCapable.buildSalaryCalcPeriod();
        //考勤月报数据
        AttendancePeriodReport monthlyReport = buildMonthlyReport();

        Map<String, Map> taxTableMap = context.taxTableHolder.getWrittenItems();
        Map<String, ExprArray> taxTables = taxTableMap.get(TaxTableProcessor.taxTableCode(personalSalaryCalcCapable.ZHCNTaxDivision(), TaxRole.NATIVE));
        calculator.setTaxTables(taxTables);

        calculator.setInputData(inputSalary);
        calculator.setReferenceData(staffRefServiceData);
        calculator.setPeriodSalaryProfile(staffPeriodSalary);
        calculator.setAttendanceMonthlyReport(monthlyReport);

        try {
            StaffSalaryCalcPeriod calcdResult = MockPersonalSalaryCalcContextHolder.getCurrentCalculator().processSinglePhased();
            MockPersonalSalaryCalcContextHolder.setCalcdResult(calcdResult);
            return calcdResult.getSummarizedData();
        } catch (Exception e) {
            logger.error("薪资计算失败", e);
            Assert.assertTrue(e instanceof Ihr360Exception);
        }
        return Maps.newHashMap();
    }


    private void buildCalcRange() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.MONTH, 2);
        calendar.set(Calendar.DATE, 1);
        Date startDate = calendar.getTime();

        calendar.set(Calendar.MONTH, 2);
        calendar.set(Calendar.DATE, 31);
        Date endDate = calendar.getTime();

        DateRange dateRange = DateRange.build(startDate, endDate);
        PersonalSalaryCalculator calculator = MockPersonalSalaryCalcContextHolder.getCurrentCalculator();
        //设置周期
        calculator.setAttendancePeriod(dateRange);
        calculator.setPayRollPeriod(dateRange);
    }

    private Map<String, DynamicCell> buildInputSalary() {
        PayrollConfigDemo payrollConfigDemo = payrollConfigRepository.findByEffectiveIs(true);
        if (payrollConfigDemo == null || payrollConfigDemo.getWrapper() == null || CollectionUtils.isEmpty(payrollConfigDemo.getWrapper().getItems())) {
            return Maps.newHashMap();
        }
        return payrollConfigDemo.getWrapper().getItems();
    }

    private Map<String, Map<String, Object>> buildRefServiceData() {
        Map<String, Map<String, Object>> ref = new HashMap<>();
        ref.put(ServiceProvider.SERVICE_ID.SIHF, ImmutableMap
                .of("SI_TYPE_0001_P", 2048.90,
                        "scee", 2048.90,
                        "HF_TYPE_0001_P", 1366.00,
                        "hfee", 1366.00));

        ref.put(ServiceProvider.SERVICE_ID.STAFF_ROSTER,
                ImmutableMap.of("enrollWorkYears", 0));

        ref.put(ServiceProvider.SERVICE_ID.STAFF_SALARY,
                ImmutableMap.of("basesalary", 20000));

        return ref;
    }

    private AttendancePeriodReport buildMonthlyReport() {
        AttendancePeriodReport report = new AttendancePeriodReport();
        com.ihr360.attendance.AttendanceReportFixedPart fixedPart = new com.ihr360.attendance.AttendanceReportFixedPart();
        fixedPart.setPaiddays(22);
        fixedPart.setSupposedworkingdays(22);
        fixedPart.setWorkingdays(21);//应出勤日-事假天数-病假天数
        report.setFixedPart(fixedPart);
        return report;
    }

    protected void fieldAssertEquals(String field, String expected) {
        Map<String, DynamicCell> data = MockPersonalSalaryCalcContextHolder.getCurrentCalcdResult().getSummarizedData();
        DynamicCell cell = data.get(field);
        if (cell != null) {
            Assert.assertEquals(field, expected, cell.getCellValue());
        } else {
            Assert.assertEquals(field, expected, "0.0");
        }
    }


}
